package fr.sedoo.rbv.geonetwork.request;

import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.commons.lang.StringUtils;
import org.jdom2.Document;
import org.jdom2.Element;

import fr.sedoo.commons.metadata.utils.domain.MetadataTools;
import fr.sedoo.commons.metadata.utils.domain.SedooMetadata;
import fr.sedoo.rbv.geonetwork.config.GeonetworkConfig;
import fr.sedoo.rbv.geonetwork.domain.GeonetworkUser;

public class MetadataByIdRequest extends AbstractCSWRequest {

	protected String id;
	private String rawXML;

	private SedooMetadata metadata;

	public MetadataByIdRequest(String id, GeonetworkUser user) {
		super(user);
		this.id = id;
	}

	public MetadataByIdRequest(String id, GeonetworkConfig config) {
		super(config);
		this.id = id;
	}

	public MetadataByIdRequest(String id) {
		super();
		this.id = id;
	}

	private String removeCSWTags(String rawXml) {
		return rawXml.replaceAll("<(/)?csw([^>]*)>", "");
	}

	@Override
	public boolean execute() throws Exception {

		Element request = getGetRecordByIdElement();
		String cswURL = getConfig().getCSWPublicationURL();
		PostMethod post = new PostMethod(cswURL);

		try {
			String postData = getString(new Document(request));
			post.setRequestEntity(new StringRequestEntity(postData,
					"application/xml", UTF8));


			String rawXml = executePostMethod(post);
			if (rawXml.length() > 0) {
				String metadataXml = removeCSWTags(rawXml);
				setRawXML(metadataXml);
				metadata = MetadataTools.fromISO19139(metadataXml);
				backwardCompatibility(metadata, rawXml);
				// metadata.getRbvExtent().getLocalisationExtent().
				return true;
			} else {
				throw new Exception();
			}

		} catch (Exception e) {
			throw new Exception(e);
		} finally {
			post.releaseConnection();
		}
	}

	/**
	 * This version ensure a backward compatibility with previous hierarchical system
	 * @param metadata
	 * @param rawXml
	 */
	private void backwardCompatibility(SedooMetadata metadata, String rawXml) 
	{
		if (rawXml.indexOf("<rbv:observatoryName>")>=0)
		{
			String name=StringUtils.substringBetween(rawXml,"<rbv:observatoryName>","</rbv:observatoryName>").trim()	;
			metadata.getDustbin().put(SedooMetadata.OBSERVATORY,name);
		}
		if (rawXml.indexOf("<rbv:drainageBasinName>")>=0)
		{
			String name=StringUtils.substringBetween(rawXml,"<rbv:drainageBasinName>","</rbv:drainageBasinName>").trim();
			metadata.getDustbin().put(SedooMetadata.EXPERIMENTAL_SITE,name);
		}
	}

	/*
	 * Namespace csw = Namespace.getNamespace("csw",
	 * "http://www.opengis.net/cat/csw/2.0.2"); Element request = new
	 * Element("GetRecordById"
	 * ,csw).setAttribute("outputSchema","csw:IsoRecord").
	 * setAttribute("service", "CSW").setAttribute("version",
	 * "2.0.2").addContent(new Element("Id",csw).setText(id)); String cswURL =
	 * getConfig().getCSWURL(); PostMethod post = new PostMethod(cswURL);
	 * 
	 * try { String postData = getString(new Document(request));
	 * post.setRequestEntity(new StringRequestEntity(postData,"application/xml",
	 * "UTF8"));
	 * 
	 * int result = httpclient.executeMethod(post); if (result ==
	 * HttpStatus.SC_OK) { InputStream responseBodyAsStream =
	 * post.getResponseBodyAsStream(); StringWriter writer = new StringWriter();
	 * IOUtils.copy(responseBodyAsStream, writer, "UTF8"); String rawXml =
	 * writer.toString(); String metadataXml = removeCSWTags(rawXml); return
	 * metadataXml; } else { throw new Exception("Cannot retrieve metadata"); }
	 * } catch (Exception e) { throw e; } finally { post.releaseConnection(); }
	 */

	private Element getGetRecordByIdElement() {
		Element element = new Element("GetRecordById", cswNamespace)
		.setAttribute("outputSchema", "csw:IsoRecord")
		.setAttribute("service", "CSW")
		.setAttribute("version", "2.0.2")
		.addContent(new Element("Id", cswNamespace).setText(id));

		Element aux = new Element("ElementSetName", cswNamespace)
		.setText("full");
		element.addContent(aux);

		return element;
	}

	public SedooMetadata getMetadata() throws Exception {
		return metadata;
	}

	public void setMetadata(SedooMetadata metadata) {
		this.metadata = metadata;
	}

	public String getRawXML() {
		return rawXML;
	}

	public void setRawXML(String rawXML) {
		this.rawXML = rawXML;
	}

}
